package com.example.service.provider.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.netflix.loadbalancer.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Configuration
public class RestTemplateConfig {

    @Autowired
    private ObjectMapper objectMapper;


    /**
     * 声明一个restful风格的http请求模板。并开启负载均衡
     * @return 返回一个restful风格的http请求模板
     */
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        RestTemplate restTemplate = new RestTemplate();
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(objectMapper);
        mappingJackson2HttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8);
        for(int i=0;i<messageConverters.size();i++){
            if(messageConverters.get(i) instanceof MappingJackson2HttpMessageConverter){
                messageConverters.set(i,mappingJackson2HttpMessageConverter);
                break;
            }
        }
        //设置要使用的消息体转换器。这些转换器用于在HTTP请求和响应时数据的转换。
        restTemplate.setMessageConverters(messageConverters);

        return restTemplate;
    }

    /**
     * 配置Ribbon负载均衡的策略
     * @return 返回一个负载均衡策略对象
     */
    @Bean
    public IRule loadBalanceStrategy(){
        //轮询算法策略
        return new RoundRobinRule();
        //随机连接策略
//        return new RandomRule();
        //重试时使用的默认负载均衡策略是轮询策略
//        return new RetryRule();
        //重试时使用的负载均衡策略。先按照轮询算法获取服务，如果获取服务失败，则在指定时间内进行重试
//        return new RetryRule(new BestAvailableRule());
        //对轮询算法进行扩展，响应速度越快的，被选择的权重越大，即越容易被选择
//        return new WeightedResponseTimeRule();
        //会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务，然后选择一个并发量最小的一个服务
//        return new BestAvailableRule();
        //先过滤掉故障实例，再选择并发较小的实例
//        return new AvailabilityFilteringRule();
        //默认使用的负载策略。判断server所在区域的性能和server的可用性来选择服务
//        return new ZoneAvoidanceRule();
    }

}
